home *** CD-ROM | disk | FTP | other *** search
- // (c) Jean MICHEL June 1993 -- any modifications must be signaled to the
- // author
-
- // Class TLifeWindow is for the main program window
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <owl.h>
- #include <commdlg.h>
- #include <dir.h>
- #include <io.h>
- #include <string.h>
- #include <filedial.h>
- #include <static.h>
- #include "efns.h"
- #include "cell.h"
- #include "shapewnd.h"
- #include "life.h"
- HPEN Pens[3]; HBRUSH Brushes[3];
- COLORREF Colors[3];
-
- class TLife : public TApplication
- {
- public:
- TLife(LPSTR AName, HINSTANCE hInstance, HINSTANCE hPrevInstance,
- LPSTR lpCmdLine, int nCmdShow)
- : TApplication(AName, hInstance, hPrevInstance, lpCmdLine, nCmdShow) {};
- virtual void InitMainWindow();
- };
-
- _CLASSDEF(TLifeWindow)
- class TLifeWindow : public TWindow
- {
- public:
- cellpop v;
- cell_type box_start,box_end;
- BOOL drawing;
- HDC DrawDC;
- int magnification;
- RECT ScrollRange;
- long gencounter;
- struct {long x;long y;}origin;// Logical coordinates of top left
- void setorigin();
- void info();
- void DrawBox();
- void Run(long count);
- cell_type coordtocell(TMessage::tagLP);
- int update(cellpop& w);
- void pixel(HDC DC,cell_type c,int color);
- char *GetFileName();
- TLifeWindow(PTWindowsObject AParent, LPSTR ATitle);
- ~TLifeWindow();
- void adjustscroll(int newmag);
- virtual void SetupWindow();
- virtual void Paint(HDC DC, PAINTSTRUCT& PS);
- virtual void WMLButtonDown(RTMessage Msg)
- = [WM_FIRST + WM_LBUTTONDOWN];
- virtual void WMRButtonDown(RTMessage Msg)
- = [WM_FIRST + WM_RBUTTONDOWN];
- virtual void WMRButtonUp(RTMessage Msg)
- = [WM_FIRST + WM_RBUTTONUP];
- virtual void WMMouseMove(RTMessage Msg)
- = [WM_FIRST + WM_MOUSEMOVE];
- virtual void CMShape(RTMessage Msg)
- = [CM_FIRST + CM_SHAPE];
- virtual void CMUFileSave(RTMessage Msg)
- = [CM_FIRST + CM_U_FILESAVEAS];
- virtual void CMUFileSaveArea(RTMessage Msg)
- = [CM_FIRST + CM_U_FILESAVEAREAAS];
- virtual void CMErase(RTMessage Msg)
- = [CM_FIRST + CM_ERASE];
- virtual void CMColorSet(RTMessage Msg)
- = [CM_FIRST + CM_COLOR_SET];
- virtual void CMColorReset(RTMessage Msg)
- = [CM_FIRST + CM_COLOR_RESET];
- virtual void CMColorUnset(RTMessage Msg)
- = [CM_FIRST + CM_COLOR_UNSET];
- virtual void CMClearGen(RTMessage Msg)
- = [CM_FIRST + CM_CLEAR_GEN];
- void CMUColor(int index);
- virtual void CMFileNew(RTMessage Msg)
- = [CM_FIRST + CM_FILENEW];
- virtual void CMHelp(RTMessage Msg)
- = [CM_FIRST + CM_HELP];
- virtual void CMHelphelp(RTMessage Msg)
- = [CM_FIRST + CM_HELPHELP];
- virtual void CMAbout(RTMessage Msg)
- = [CM_FIRST + CM_ABOUT];
- virtual void CMZoomOut(RTMessage Msg)
- = [CM_FIRST + CM_ZOOMOUT];
- virtual void CMZoomIn(RTMessage Msg)
- = [CM_FIRST + CM_ZOOMIN];
- virtual void CMStep(RTMessage Msg)
- = [CM_FIRST + CM_STEP];
- virtual void CMRun(RTMessage Msg)
- = [CM_FIRST + CM_RUN];
- };
-
- int mags[]={1,2,3,5,7,10,15,25};int magindex=4;
-
- TLifeWindow::TLifeWindow(PTWindowsObject AParent, LPSTR ATitle)
- : TWindow(AParent, ATitle)
- { AssignMenu("COMMANDS");
- Attr.Style|= WS_VSCROLL|WS_HSCROLL;
- magnification=mags[magindex];origin.x=origin.y=0;
- drawing=FALSE;
- Scroller=new TScroller(this,1,1,1,1); // meaningless values -- setup by SetupWindow
- selected_shape=cellpop("o\n");
- v=cellpop();gencounter=0;
- Colors[UNSET]=RGB(120,255,120);
- Colors[SET]=RGB(255,0,0);
- Colors[RESET]=RGB(200,0,0);
- for(int i=0;i<3;i++)
- { Brushes[i]=CreateSolidBrush(Colors[i]);
- Pens[i]=CreatePen(PS_SOLID,1,Colors[i]);
- }
- }
-
- void TLifeWindow::SetupWindow()
- { TWindow::SetupWindow();
- RECT r;GetClientRect(HWindow,&r);
- ScrollRange.left=-(r.right-r.left)/(2*magnification);
- ScrollRange.top=-(r.bottom-r.top)/(2*magnification);
- ScrollRange.right=ScrollRange.left+1;
- ScrollRange.bottom=ScrollRange.top+1;
- Scroller->AutoOrg=FALSE;
- adjustscroll(magnification);
- readshapelib("life.lib");
- }
-
- TLifeWindow::~TLifeWindow()
- { for(int i=0;i<3;i++)
- { DeleteObject(Brushes[i]);
- DeleteObject(Pens[i]);
- }
- }
-
- void TLifeWindow::Paint(HDC DC, PAINTSTRUCT&)
- { setorigin();
- for(int i=0;i<v.pop;i++)pixel(DC,v.v[i],RESET);
- info();
- }
-
- void TLifeWindow::info()
- { RECT r;GetClientRect(HWindow,&r);
- char text[130];
- sprintf(text,
- "Life Pop:%5d Gen:%5ld Mag:%d X:[%ld,%ld] Y:[%ld,%ld]",
- v.pop,gencounter,magnification,
- Scroller->XPos+ScrollRange.left,Scroller->XPos+ScrollRange.left+(r.right-r.left)/magnification,
- Scroller->YPos+ScrollRange.top,Scroller->YPos+ScrollRange.top+(r.bottom-r.top)/magnification);
- SetCaption(text);
- }
-
- int TLifeWindow::update(cellpop& w)
- { int iw=0,iv=0,nbchg=0;
- DrawDC = GetDC(HWindow);
- setorigin();
- while(iw!=w.pop || iv!=v.pop)
- { if (w.v[iw]<v.v[iv]){ pixel(DrawDC,w.v[iw],SET);nbchg++;iw++;}
- else if(w.v[iw]==v.v[iv]){ pixel(DrawDC,w.v[iw],RESET);iw++;iv++;}
- else { pixel(DrawDC,v.v[iv],UNSET);nbchg++;iv++;}
- }
- ReleaseDC(HWindow, DrawDC);
- v=w;info();
- return nbchg;
- }
-
- void TLifeWindow::setorigin()
- { origin.x=Scroller->XPos+ScrollRange.left;
- origin.y=Scroller->YPos+ScrollRange.top;
- }
-
- void TLifeWindow::pixel(HDC DC,cell_type c,int color)
- { int border=magnification>3,x,y;
- SelectObject(DC,Pens[color]);
- SelectObject(DC,Brushes[color]);
- x=magnification*(c.cellx()-origin.x);
- y=magnification*(c.celly()-origin.y);
- if(magnification>1)
- Rectangle(DC,x,y,x+magnification-border,y+magnification-border);
- else SetPixel(DC,x,y,Colors[color]);
- }
-
- cell_type TLifeWindow::coordtocell(TMessage::tagLP LP)
- { return cell_type(LP.Lo/magnification+origin.x,LP.Hi/magnification+origin.y);}
-
- void TLifeWindow::WMLButtonDown(RTMessage Msg)
- { cellpop w=v;
- w.add(w,selected_shape,coordtocell(Msg.LP),LAY_XOR);
- if(selected_shape.pop!=1)selected_shape="o";
- update(w);
- }
-
- void TLifeWindow::DrawBox()
- { int x1=magnification*(box_start.cellx()-origin.x);
- int y1=magnification*(box_start.celly()-origin.y);
- int x2=magnification*(box_end.cellx()-origin.x);
- int y2=magnification*(box_end.celly()-origin.y);
- DrawDC=GetDC(HWindow);
- SetROP2(DrawDC,R2_NOT);
- MoveTo(DrawDC,x1,y1);
- LineTo(DrawDC,x1,y2);
- LineTo(DrawDC,x2,y2);
- LineTo(DrawDC,x2,y1);
- LineTo(DrawDC,x1,y1);
- ReleaseDC(HWindow,DrawDC);
- }
-
- void TLifeWindow::WMRButtonDown(RTMessage Msg)
- { drawing=TRUE;SetCapture(HWindow);
- DrawBox();box_start=box_end=coordtocell(Msg.LP);DrawBox();
- }
-
- void TLifeWindow::WMMouseMove(RTMessage Msg)
- { if(drawing)
- { DrawBox(); box_end=coordtocell(Msg.LP);DrawBox();}
- #if 0
- setorigin();
- char buf[20]; sprintf(buf,"%04ld,%04ld",origin.x,origin.y);
- DrawDC = GetDC(HWindow);
- TextOut(DrawDC,10,10,buf,strlen(buf));
- ReleaseDC(HWindow,DrawDC);
- #endif
- }
-
- void TLifeWindow::WMRButtonUp(RTMessage Msg)
- { drawing=FALSE;
- ReleaseCapture();
- }
-
- void TLifeWindow::Run(long count)
- { MSG msg;//PeekMessage(&msg,NULL,0,0,PM_REMOVE);
- cellpop w,res;res.pop=-1;
- do
- { w.nextgen(v);
- if(w.error())return;
- if(w==v){efns(WARNING_,"stable");return;}
- if(w==res){efns(WARNING_,"period 2");return;}
- gencounter++;res=v;
- update(w);
- if(w.pop==0){efns(WARNING_,"dead");return;}
- if( PeekMessage(&msg,NULL,0x00A1,0x0209,PM_REMOVE))
- { TranslateMessage(&msg);
- DispatchMessage(&msg);
- if((msg.message<=0xA9 || msg.message>=0x106)
- && (msg.message<=0x108 || msg.message>=0x201))
- break;
- }
- }
- while(--count>0);
- }
-
- void TLifeWindow::CMStep(RTMessage m){Run(1);}
-
- void TLifeWindow::CMRun(RTMessage m){Run(10000);}
-
- void TLifeWindow::adjustscroll(int newmag)
- { RECT r;GetClientRect(HWindow,&r);
- Scroller->XPos+=(newmag-magnification)*(r.right-r.left)/(2*newmag*magnification);
- Scroller->YPos+=(newmag-magnification)*(r.bottom-r.top)/(2*newmag*magnification);
- magnification=newmag;
- Scroller->XLine=Scroller->YLine=25/magnification;
- Scroller->SetUnits(magnification,magnification);
- RECT NewRange;
- if(v.pop>0)
- { NewRange.left=v.firstx().cellx();
- NewRange.right=v.lastx().cellx();
- NewRange.top=v.firsty().celly();
- NewRange.bottom=v.lasty().celly();
- }
- else
- { NewRange.left=0;
- NewRange.right=0;
- NewRange.top=0;
- NewRange.bottom=0;
- }
- NewRange.left-=(r.right-r.left)/magnification;
- NewRange.top-=(r.bottom-r.top)/magnification;
- Scroller->XPos+=ScrollRange.left-NewRange.left;
- Scroller->YPos+=ScrollRange.top-NewRange.top;
- ScrollRange=NewRange;
- Scroller->SetRange(ScrollRange.right-ScrollRange.left,ScrollRange.bottom-ScrollRange.top);
- InvalidateRect(HWindow, NULL, TRUE);
- }
-
- void TLifeWindow::CMZoomIn(RTMessage)
- { if(magnification==25)return;
- adjustscroll(mags[++magindex]);
- }
-
- void TLifeWindow::CMZoomOut(RTMessage)
- { if(magnification==1)return;
- adjustscroll(mags[--magindex]);
- }
-
- void TLifeWindow::CMFileNew(RTMessage)
- { v.clear_pop();gencounter=0;
- InvalidateRect(HWindow, NULL, TRUE);}
-
- void TLifeWindow::CMErase(RTMessage)
- { cellpop w=v;
- w.erase_rect(box_start,box_end);update(w);
- DrawBox();box_end=box_start;
- }
-
- char *TLifeWindow::GetFileName()
- { OPENFILENAME ofnTemp;
- static char FileName[MAXPATH];
- char szTemp[] = "All Files (*.*)\0*.*\0Life Files (*.lfe)\0*.lfe\0";
- /*
- Some Windows structures require the size of themselves in an effort to
- provide backward compatibility with future versions of Windows. If the
- lStructSize member is not set the call to GetOpenFileName() will fail.
- */
- ofnTemp.lStructSize = sizeof( OPENFILENAME );
- ofnTemp.hwndOwner = HWindow; // An invalid hWnd causes non-modality
- ofnTemp.hInstance = 0;
- ofnTemp.lpstrFilter = (LPSTR)szTemp; // See previous note concerning string
- ofnTemp.lpstrCustomFilter = NULL;
- ofnTemp.nMaxCustFilter = 0;
- ofnTemp.nFilterIndex = 2;
- FileName[0]='\0';
- ofnTemp.lpstrFile = FileName; // Stores the result in this variable
- ofnTemp.nMaxFile = sizeof( FileName );
- ofnTemp.lpstrFileTitle = NULL;
- ofnTemp.nMaxFileTitle = 0;
- ofnTemp.lpstrInitialDir = NULL;
- ofnTemp.lpstrTitle = "Save Area"; // Title for dialog
- ofnTemp.Flags = OFN_HIDEREADONLY | OFN_NOREADONLYRETURN|OFN_OVERWRITEPROMPT;
- ofnTemp.nFileOffset = 0;
- ofnTemp.nFileExtension = 0;
- ofnTemp.lpstrDefExt = "lfe";
- ofnTemp.lCustData = NULL;
- ofnTemp.lpfnHook = NULL;
- ofnTemp.lpTemplateName = NULL;
- /*
- If the call to GetOpenFileName() fails you can call CommDlgExtendedError()
- to retrieve the type of error that occured.
- */
- if(GetSaveFileName( &ofnTemp ) != TRUE)
- { DWORD Errval=CommDlgExtendedError();
- if(Errval!=0) // 0 value means user selected Cancel
- efns(WARNING_,"GetSaveFileName returned Error #%ld",Errval);
- }
- return FileName;
- }
-
- void TLifeWindow::CMUFileSave( RTMessage )
- {v.save(GetFileName());}
-
- void TLifeWindow::CMUFileSaveArea( RTMessage )
- { DrawBox();
- v.save_rect(GetFileName(),box_start,box_end);
- box_end=box_start;
- }
-
- void TLifeWindow::CMColorUnset(RTMessage Msg){CMUColor(UNSET);}
- void TLifeWindow::CMColorReset(RTMessage Msg){CMUColor(RESET);}
- void TLifeWindow::CMColorSet(RTMessage Msg){CMUColor(SET);}
- void TLifeWindow::CMClearGen(RTMessage Msg){gencounter=0;info();}
-
-
- void TLifeWindow::CMUColor(int index)
- { CHOOSECOLOR ccTemp;
- COLORREF crTemp[16]; // Important, sometimes unused, array
-
- ccTemp.lStructSize = sizeof( CHOOSECOLOR );
- ccTemp.hwndOwner = HWindow;
- ccTemp.hInstance = 0;
- ccTemp.rgbResult = Colors[index]; // CC_RGBINIT flag makes this the default color
- /*
- lpCustColors must be set to a valid array of 16 COLORREF's, even if it
- is not used. If it isn't you will probably fail with a GP fault in
- COMMDLG.DLL.
- */
- ccTemp.lpCustColors=crTemp;
- ccTemp.Flags= CC_RGBINIT;
- ccTemp.lCustData=0L;
- ccTemp.lpfnHook=NULL;
- ccTemp.lpTemplateName=NULL;
- if(ChooseColor(&ccTemp)==TRUE)
- { Colors[index]=ccTemp.rgbResult;
- DeleteObject(Brushes[index]);
- DeleteObject(Pens[index]);
- Brushes[index]=CreateSolidBrush(Colors[index]);
- Pens[index]=CreatePen(PS_SOLID,1,Colors[index]);
- InvalidateRect( HWindow, NULL, TRUE );
- }
- }
-
- void TLifeWindow::CMHelp(RTMessage)
- { WinHelp(HWindow,"LIFE.HLP",HELP_CONTENTS,0l);}
-
- void TLifeWindow::CMHelphelp(RTMessage)
- { WinHelp(HWindow,NULL,HELP_HELPONHELP,0l);}
-
- void TLifeWindow::CMAbout(RTMessage Msg)
- { MessageBox(HWindow,"Windows Life\n\n"
- "Version 0.1 June 1993\n\n"
- "(C) Jean MICHEL\n\n"
- " 22, rue de Wattignies 75012 Paris France\n"
- " E-Mail: michel@dmi.ens.fr","About Life",MB_OK);}
-
- void TLifeWindow::CMShape(RTMessage)
- { PTWindow ShapeWindow;
- ShapeWindow = new TShapeWindow(this);
- GetApplication()->MakeWindow(ShapeWindow);
- }
-
- void TLife::InitMainWindow()
- { MainWindow = new TLifeWindow(NULL, Name);
- }
-
- #include "winerror.h"
- void (cdecl *efns)(int errcode,char *fmt,...)=error;
-
- int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
- LPSTR lpCmdLine, int nCmdShow)
- { TLife Life("Windows Life (C) Jean MICHEL Version 0.0", hInstance, hPrevInstance,
- lpCmdLine, nCmdShow);
- Life.Run();
- return Life.Status;
- }
-